package com.liwenfeng.tcpandupd;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class TcpMultipleServer {
    public List<Socket> acceptSockets = new ArrayList<>();

    public static void main(String[] args) {
        new TcpMultipleServer().server();
    }

    public void server() {
        System.out.println("支持多客户端的服务端启动了，等待接收数据...");
        try (
                //1.创建ServerSockert对象，同时注册端口号。
                ServerSocket socket = new ServerSocket(8888);

        ) {
            while (true) {
                try {
                    //2.调用accept方法，阻塞等待客户端的连接请求
                    Socket acceptSocket = socket.accept();

                    System.out.println("有人上线了：" + acceptSocket.getRemoteSocketAddress());
                    sendMsgToAll("有人上线了：" + acceptSocket.getRemoteSocketAddress());
                    acceptSockets.add(acceptSocket);
                    //创建新线程，接收新连接的数据，socket连接是长连接，断开后read方法会抛异常
                    CompletableFuture.runAsync(() -> {
                        try (
                                //3.从socket通信管道得到一个字节输入流
                                InputStream is = acceptSocket.getInputStream();
                                //4.把原始字节输入流包装成数据输入流
                                DataInputStream dis = new DataInputStream(is);
                        ) {
                            String msg = null;
                            while (true) {
                                try {
                                    msg = acceptSocket.getRemoteSocketAddress() + "：" + dis.readUTF();
                                    sendMsgToAll(msg);
                                    System.out.println(msg);
                                } catch (IOException e) {
                                    System.out.println(acceptSocket.getRemoteSocketAddress() + "离线了...");
                                    sendMsgToAll(acceptSocket.getRemoteSocketAddress() + "离线了...");
                                    acceptSockets.remove(acceptSocket);
                                    break;
                                }
                            }
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    });
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void sendMsgToAll(String msg) {
        for (Socket acceptSocket : acceptSockets) {
            try {
                OutputStream os = acceptSocket.getOutputStream();
                DataOutputStream dos = new DataOutputStream(os);

                dos.writeUTF(msg);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
